import {
    BufferGeometry, Vector3, Matrix4, BufferAttribute, InterleavedBufferAttribute, Mesh,
    Euler, PlaneGeometry, Color, MeshPhongMaterial,
    Group,
    ShapeGeometry,
    Sphere,
    SphereGeometry, CylinderGeometry, BoxGeometry, PerspectiveCamera, Object3D,
} from "three";

const angle = Math.PI / 180;

export default class Tank extends Mesh {

    private obj3Ds: Object3D[] = [];
    private camera: PerspectiveCamera;
    private former: Vector3;
    private s: number = 0.1;
    private rots: number = 0.5 * Math.PI / 180;
    private moveState: number = 0;
    private rotState: number = 0;

    public eye: Vector3 = new Vector3(0, 4, -5);
    public _lookAt: Vector3 = new Vector3(0, 4, 0);

    constructor() {
        super();

        this.camera = new PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
        this.former = new Vector3(0, 0, 1);

        this.init();

        this.update();
    }

    private init() {
        const { obj3Ds, camera } = this;
        //车身
        const sphere = new Mesh(new SphereGeometry(1), new MeshPhongMaterial({ color: new Color(0.6, 0.6, 0.6) }));
        sphere.position.set(0, 1.5, 0);
        this.add(sphere);
        //车轮
        const clgeo = new CylinderGeometry(0.7, 0.7, 0.2);
        clgeo.applyMatrix4(new Matrix4().setPosition(0.7, 1.1, 0));
        const clmat = new MeshPhongMaterial({ color: new Color(0.6, 0.6, 0.6) });
        const cll = new Mesh(clgeo, clmat);
        cll.rotateZ(90 * angle);
        const clr = new Mesh(clgeo, clmat);
        clr.rotateZ(90 * angle);
        clr.position.x = 2.2;
        this.add(cll);
        this.add(clr);
        //炮口
        const boxGroup = new Group();
        boxGroup.position.set(0, 2, 0);
        const boxGeo = new BoxGeometry(0.5, 0.5, 4);
        const box = new Mesh(boxGeo, new MeshPhongMaterial({ color: new Color(0.2, 0.2, 0.6) }));
        box.position.z = 2;
        boxGroup.add(box);
        this.add(boxGroup);

        obj3Ds.push(sphere, cll, clr, boxGroup);

        obj3Ds.forEach(u => {
            u.castShadow = true;
        });

        camera.position.copy(this.eye);
        camera.lookAt(this._lookAt);
        this.add(camera);
    }

    public move(forward: number) {
        this.moveState = forward;
    }

    public rot(lr: number) {
        this.rotState = lr;
    }

    private update() {
        const { moveState, rotState, former, s, rots, _lookAt, camera } = this;
        let moveS = new Vector3();
        if (moveState > 0) {
            moveS = former.clone().multiplyScalar(s);
        } else if (moveState < 0) {
            moveS = former.clone().multiplyScalar(-s);
        }
        this.position.add(moveS);
        //_lookAt.copy(new Vector3(this.position.x, 4, this.position.z));


        if (rotState > 0) {
            former.copy(former.applyMatrix4(new Matrix4().makeRotationY(rots))).normalize();
            this.rotateY(rots);
        } else if (rotState < 0) {
            former.copy(former.applyMatrix4(new Matrix4().makeRotationY(-rots))).normalize();
            this.rotateY(-rots);
        }


        requestAnimationFrame(() => {
            // this.update();
        });
    }

    public setPosi(pos: Vector3) {
        this.position.copy(pos.clone());
    }

    public setFormer(former: Vector3) {
        this.former.copy(former.clone());
        this.lookAt(former.clone());
    }

    public rotCannon(target: Vector3) {
        const { obj3Ds } = this;
        obj3Ds[3].lookAt(target.clone());
    }

    public getCamera() {
        return this.camera;
    }

}